package com.globalwave.common.Validator;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;


/**
 * 
 * 银行帐号
 * 
 * @author Virgil
 */
public class AccountValidator {

    private static Map<String, int[][]> parityBitMap ;
    
    static {
        parityBitMap = new HashMap<String, int[][]>() ;
        // key:银行代码，value:校验码数组，参见：checkSum()说明
        //parityBitMap.put("006", new int[][]{{ 7,6,5,4,3,2,7,6,5,4,3,2, 1,  11 }}) ;
        //parityBitMap.put("007", new int[][]{{ 4,3,2,8,7,6,5,4,3,2,     1,  11 }}) ;
        //parityBitMap.put("008", new int[][]{{ 7,9,3,7,9,3,7,9,3,7,9,   1,  11 }}) ;
        //parityBitMap.put("009", new int[][]{{ 2,1,9,0,7,6,5,4,3,2,1,   1,  10 }}) ;
        //parityBitMap.put("013", new int[][]{{ 6,5,4,3,2,7,6,5,4,3,2,   1,  11 }}) ;
        //parityBitMap.put("700", new int[][]{{ 2,3,4,5,6,7,             1,  11 },
        //                                     { 2,3,4,5,6,7,             1,  11 }}) ;
        //parityBitMap.put("801", new int[][]{{ 1,5,7,3,1,               1,  11 },
        //                                     { 2,3,4,5,6,7,2,           1,  9  }}) ;
        //parityBitMap.put("822", new int[][]{{ 3,7,1,3,7,1,3,7,1,3,7,   1,  10 }}) ;
        

        parityBitMap.put("DocId", new int[][]{{ 7,4,3,4,1,2,9,6,5,6,3,2, 1,  11 }}) ;
        
    }
    /*
    public boolean check(String blankNumber, String accountNumber) {
        if ("006".equals(blankNumber)
                || "007".equals(blankNumber)
                || "008".equals(blankNumber)
                || "009".equals(blankNumber)
                || "013".equals(blankNumber)
                || "822".equals(blankNumber)) {
            
            return checkSum(accountNumber, ((int[][])parityBitMap.get(blankNumber))[0]) ;
            
        } else if ("700".equals(blankNumber)) {
            int[][] parityBits = ((int[][])parityBitMap.get(blankNumber)) ;
            
            return checkSum(accountNumber.substring(0,7), parityBits[0]) 
            			&& checkSum(accountNumber.substring(7), parityBits[1]) ;
            
        } else if ("801".equals(blankNumber)) {
            int[][] parityBits = ((int[][])parityBitMap.get(blankNumber)) ;
            
            if ("003".equals(accountNumber.substring(3, 6))) {
                return checkSum(accountNumber.substring(8), parityBits[0]) ;
            } else {
                int a = Integer.parseInt(accountNumber.substring(0,3)) * 10;
                int b = Integer.parseInt(accountNumber.substring(3,6)) * 10;
                int c = Integer.parseInt(accountNumber.substring(6));
                //StringUtils.rightPad(str, size)
                return checkSum(PubFunc.fillString(String.valueOf(a + b + c), 7), parityBits[1]) ;
            }
        } 
        
        return true ;
    }
    */
    /**
     * 求"和"校验，算法为：
     * 帐  号：abc...defg H   -- H为校验位
     * 校验码：mno...pqrs t u -- t通常为1，u为被除数
     * 
     * 公式：a*m + b*n + c*o + ... + d*p + e*q + f*r + g*s = total
     *       (u - total%u - H*t) % 10 = result
     * 
     * if resutl == 0 , then return true ; else return false ; 
     * 
     * @param accountNumber 帐号，不一定是银行贴的全部，可能只是一部分
     * @param parityBit  校验码，校验码长度是帐号长度+1
     * @return 通过校验，返回true
     */
    private boolean checkSum(String accountNumber, int[] parityBit) {
        
        int total = 0 ;
        int remainder = 0 ;
        
        // 叉乘非校验位数值
        for (int i = parityBit.length - 3 ; i >=0 ; i --) {
            final int a = Character.getNumericValue(accountNumber.charAt(i)) ;
            final int b = parityBit[i];
            total += a * b ;
        }
        
        remainder = total % parityBit[parityBit.length - 1] ;

        // 取得校验位因子，b通常为1。
        final int a = Character.getNumericValue(accountNumber.charAt(parityBit.length - 2)) ;
        final int b = parityBit[parityBit.length - 2];
        
        return ((parityBit[parityBit.length - 1] - remainder - a*b) % 10) == 0 ;    
    }
    
    public int getDocumentIdValidateBit(Long idseq) {
    	String idAsString = StringUtils.leftPad(String.valueOf(idseq), 12, '0') ;
    	
    	for (int i = 0 ; i < 10 ; i ++) {
	    	if (checkSum(idAsString + i, parityBitMap.get("DocId")[0])) {
	    		return i;
	    	}
    	}
    	
    	return -1 ;
    }
}
